﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace Formatter
{
    class Formatter
    {
        private static List<string> m_errors = new List<string>();
        private static List<string> m_files = new List<string>();

        private const string UNCRUSTIFY_EXE = @"C:\Program Files (x86)\UniversalIndentGUI\indenters\uncrustify.exe";
        private const string UNCRUSTIFY_CFG = "uncrustify.cfg";

        private static string CFG = "";

        public static void Main(string[] args)
        {
            Console.WriteLine();
            Console.WriteLine();

            if (args.Length < 1)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine();
                Console.WriteLine("FORMATTER ERROR. Parameter missing.");
                Console.ReadKey();
                return;
            }

            CFG = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\..\\..\\" + 
                UNCRUSTIFY_CFG;

            if (!new FileInfo(CFG).Exists)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine();
                Console.WriteLine("FORMATTER ERROR. Can't find: {0}", CFG);
                Console.ReadKey();
                return;
            }

            if (!new FileInfo(UNCRUSTIFY_EXE).Exists)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine();
                Console.WriteLine("FORMATTER ERROR. Can't find: {0}", UNCRUSTIFY_EXE);
                Console.ReadKey();
                return;
            }

            foreach (var arg in args)
            {
                Console.WriteLine(arg);

                var di = new DirectoryInfo(arg);
                var fi = new FileInfo(arg);

                if (di.Exists)
                    FindFiles(di);
                else if (fi.Exists)
                    m_files.Add(fi.FullName);
            }
            

            m_files = m_files.OrderBy(s => s).ToList();
            m_files = m_files.Where(s => Path.GetFileName(s) != "aros.rom.cpp").ToList();

            if (!m_files.Any())
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine();
                Console.WriteLine("FORMATTER ERROR. No files. Press a key to exit...");
                Console.ReadKey();
                return;
            }

            ProcessFiles();

            Console.WriteLine();

            if (m_errors.Count != 0)
            {
                Console.ForegroundColor = ConsoleColor.Yellow;
                Console.WriteLine("FORMATTER WARNING. Something goes wrong with: ");
                foreach (var file in m_errors)
                    Console.WriteLine(file);
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("OK");
            }

            Console.ReadKey();
        }

        private static void FindFiles(DirectoryInfo a_di)
        {
            m_files.AddRange(from file in a_di.EnumerateFiles()
                             where (file.Extension.ToLower() == ".cpp") ||
                                   (file.Extension.ToLower() == ".c") ||
                                   (file.Extension.ToLower() == ".h")
                             select file.FullName);

            foreach (var di in a_di.EnumerateDirectories())
                FindFiles(di);
        }

        private static void ProcessFiles()
        {
            foreach (var file in m_files)
            {
                Console.ForegroundColor = ConsoleColor.Cyan;
                Console.WriteLine(String.Format("Processing file ({0}/{1}): {2}", m_files.IndexOf(file) + 1,
                    m_files.Count, file));
                Console.ForegroundColor = ConsoleColor.White;

                ProcessStartInfo si = new ProcessStartInfo(UNCRUSTIFY_EXE);

                si.UseShellExecute = false;
                si.Arguments = String.Format("-c \"{0}\" --no-backup \"{1}\"", CFG, file);

                var process = Process.Start(si);
                process.WaitForExit();

                if (process.ExitCode != 0)
                {
                    if (process.ExitCode == 1)
                    {
                        lock (m_errors)
                        {
                            m_errors.Add(file);
                        }
                    }
                }
            }
        }
    }
}
